/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.florent37.camerafragment.internal.ui;

import com.github.florent37.camerafragment.CameraFractionApi;
import com.github.florent37.camerafragment.ResourceTable;
import com.github.florent37.camerafragment.configuration.Configuration;
import com.github.florent37.camerafragment.configuration.ConfigurationProvider;
import com.github.florent37.camerafragment.configuration.ConfigurationProviderImpl;
import com.github.florent37.camerafragment.internal.controller.CameraController;
import com.github.florent37.camerafragment.internal.controller.impl.Camera1Controller;
import com.github.florent37.camerafragment.internal.controller.view.CameraView;
import com.github.florent37.camerafragment.internal.enums.Flash;
import com.github.florent37.camerafragment.internal.enums.MediaAction;
import com.github.florent37.camerafragment.internal.enums.Record;
import com.github.florent37.camerafragment.internal.timer.CountdownTask;
import com.github.florent37.camerafragment.internal.timer.TimerTask;
import com.github.florent37.camerafragment.internal.timer.TimerTaskBase;
import com.github.florent37.camerafragment.internal.ui.model.PhotoQualityOption;
import com.github.florent37.camerafragment.internal.ui.model.VideoQualityOption;
import com.github.florent37.camerafragment.internal.utils.Log;
import com.github.florent37.camerafragment.internal.utils.Size;
import com.github.florent37.camerafragment.internal.utils.Utils;
import com.github.florent37.camerafragment.listeners.CameraFragmentControlsListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentResultListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentStateListener;
import com.github.florent37.camerafragment.listeners.CameraFragmentVideoRecordTextListener;

import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.media.camera.device.CameraInfo;
import ohos.sensor.agent.CategoryLightAgent;
import ohos.sensor.agent.CategoryOrientationAgent;
import ohos.sensor.bean.CategoryLight;
import ohos.sensor.bean.CategoryOrientation;
import ohos.sensor.data.CategoryLightData;
import ohos.sensor.data.CategoryOrientationData;
import ohos.sensor.listener.ICategoryLightDataCallback;
import ohos.sensor.listener.ICategoryOrientationDataCallback;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 展示相机页面
 *
 * @since 2021-04-15
 */
public class BaseAnncaFraction extends Fraction implements CameraFractionApi,
    ListContainer.ItemClickedListener, ListContainer.ItemLongClickedListener, Component.ClickedListener {
    private static final String TAG = "BaseAnncaFraction";
    private static final String ARG_CONFIGURATION = "configuration";
    private static final long INTERVAL = 100000000L;
    private static final int DEFAULT = -1;
    private static final int DEFAULT_1 = 1;
    private static final int DEFAULT_2 = 2;
    private static final int DEFAULT_3 = 3;
    private static final int NEGATIVE_3 = -3;
    private static final int DEGREE_90 = 90;
    private static final int DEGREE_180 = 180;
    private static final int DEGREE_270 = 270;
    private static final int FLASH_CONSTANT = 150;
    private static final int MATRIX_LENGTH = 9;
    private static final int ROTATION_VECTOR_LENGTH = 9;
    private static final int NUMBER_1024 = 1024;
    private static final float ROTATION_1_80 = -1.80f;
    private static final float ROTATION_2_43 = -2.43f;
    private static final float ROTATION_2_72 = 2.72f;
    private static final float ROTATION_2_85 = 2.85f;
    private static final float ROTATION_3_12 = 3.12f;
    private static final float ROTATION_3_14 = 3.14f;
    private static final float SCALE_0_5 = 0.5f;
    private static final int SCALE_TIME_60 = 60;
    private static final int SCALE_TIME_80 = 80;
    private static final String MB = "Mb";
    private CharSequence[] videoQualities;
    private CharSequence[] photoQualities;
    private ConfigurationProvider configurationProvider;
    private int newVideoQuality = DEFAULT;
    private int newPhotoQuality = DEFAULT;
    private int currentFlashMode = Flash.FLASH_AUTO;
    private int currentCameraType = CameraInfo.FacingType.CAMERA_FACING_BACK;
    private int currentMediaActionState = MediaAction.ACTION_PHOTO;
    private int currentRecordState = Record.TAKE_PHOTO_STATE;
    private Component component;
    private CommonDialog settingsDialog;
    private Configuration configuration;
    private AnimatorProperty animatorProperty;
    private AnimatorProperty animatorProperty1;
    private DirectionalLayout surfaceProvider;
    private CameraController cameraController;
    private CategoryOrientationAgent sensorManager = null;
    private CategoryLightAgent categoryLightAgent = null;
    private CameraFragmentControlsListener cameraFragmentControlsListener;
    private CameraFragmentResultListener cameraFragmentResultListener;
    private CameraFragmentVideoRecordTextListener cameraFragmentVideoRecordTextListener;
    private CameraFragmentStateListener cameraFragmentStateListener;
    private int index = DEFAULT; // 记录点击位置
    private long maxVideoFileSize;
    private boolean isBackground = false;
    private TimerTaskBase countDownTimer;
    private List<Component> componentList = new ArrayList<>(); // 把当前控件保存起来
    private EventHandler eventHandler = new EventHandler(EventRunner.getMainEventRunner());

    private final TimerTaskBase.Callback timerCallBack = new TimerTaskBase.Callback() {
        @Override
        public void setText(String text) {
            if (cameraFragmentVideoRecordTextListener != null) {
                cameraFragmentVideoRecordTextListener.setRecordDurationText(text);
            }
        }

        @Override
        public void setTextVisible(boolean isVisible) {
            if (cameraFragmentVideoRecordTextListener != null) {
                cameraFragmentVideoRecordTextListener.setRecordDurationTextVisible(isVisible);
            }
        }
    };

    private final ICategoryOrientationDataCallback sensorEventListener = new ICategoryOrientationDataCallback() {
        @Override
        public void onSensorDataModified(CategoryOrientationData categoryOrientationData) {
            // 对接收的categoryOrientationData传感器数据对象解析和使用
            float[] rotationMatrix = new float[MATRIX_LENGTH];
            CategoryOrientationData.getDeviceRotationMatrix(rotationMatrix,
                categoryOrientationData.values); // 根据旋转矢量传感器的数据获得旋转矩阵
            float[] rotationAngle = new float[ROTATION_VECTOR_LENGTH];
            rotationAngle = CategoryOrientationData.getDeviceOrientation(rotationMatrix,
                rotationAngle); // 根据计算出来的旋转矩阵获取设备的方向
            String substring = String.valueOf(rotationAngle[1]);
            if (rotationAngle[0] < 0 && rotationAngle[0] > NEGATIVE_3) {
                // UP
                configurationProvider.setSensorPosition(Configuration.SENSOR_POSITION_UP);
                configurationProvider.setDegrees(0);
            } else {
                if (rotationAngle[DEFAULT_2] > ROTATION_2_43 && rotationAngle[DEFAULT_2] < ROTATION_1_80) {
                    // LEFT
                    configurationProvider.setSensorPosition(Configuration.SENSOR_POSITION_LEFT);
                    configurationProvider.setDegrees(DEGREE_90);
                } else if (rotationAngle[DEFAULT_2] < ROTATION_2_85 && rotationAngle[DEFAULT_2] > ROTATION_2_72) {
                    // RIGHT
                    configurationProvider.setSensorPosition(Configuration.SENSOR_POSITION_RIGHT);
                    configurationProvider.setDegrees(DEGREE_270);
                } else if (!substring.contains("E") && rotationAngle[DEFAULT_2] < ROTATION_3_14
                    && rotationAngle[DEFAULT_2] > ROTATION_3_12) {
                    // UP SIDE DOWN
                    configurationProvider.setSensorPosition(Configuration.SENSOR_POSITION_UP_SIDE_DOWN);
                    configurationProvider.setDegrees(DEGREE_180);
                }
            }
            eventHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    cameraController.setScreenRotation(configurationProvider.getDegrees());
                    onScreenRotation(configurationProvider.getDegrees());
                }
            });
        }

        @Override
        public void onAccuracyDataModified(CategoryOrientation categoryOrientation, int ii) {
            // 使用变化的精度
        }

        @Override
        public void onCommandCompleted(CategoryOrientation categoryOrientation) {
            // 传感器执行命令回调
        }
    };
    private final ICategoryLightDataCallback lightDataCallback = new ICategoryLightDataCallback() {
        @Override
        public void onSensorDataModified(CategoryLightData categoryLightData) {
            float[] values = categoryLightData.getValues();
            int flashMode = configurationProvider.getFlashMode();
            if (flashMode == Configuration.FLASH_MODE_AUTO) {
                if (values[0] < FLASH_CONSTANT) {
                    // 当前闪光灯模式为自动时根据环境光进行开启
                    cameraController.openFlashLight();
                } else {
                    // 关闭闪光灯
                    cameraController.closeFlashLight();
                }
            }
        }

        @Override
        public void onAccuracyDataModified(CategoryLight categoryLight, int ii) {
        }

        @Override
        public void onCommandCompleted(CategoryLight categoryLight) {
        }
    };

    /**
     * 实例化
     *
     * @param fragment Fraction
     * @param configuration 配置项
     * @return Fraction页面碎片
     */
    public static Fraction newInstance(Fraction fragment, Configuration configuration) {
        Intent intent = new Intent();
        intent.setParam(ARG_CONFIGURATION, configuration);
        FractionAbility fractionAbility = fragment.getFractionAbility();
        if (fractionAbility != null) { // 这里获取为空
            fractionAbility.setIntent(intent);
        }
        return fragment;
    }

    @Override
    protected Component onComponentAttached(LayoutScatter scatter, ComponentContainer container, Intent intent) {
        component = scatter.parse(ResourceTable.Layout_generic_camera, container, false);
        return component;
    }

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        if (intent != null) {
            configuration = intent.getSerializableParam(ARG_CONFIGURATION);
        }
        this.configurationProvider = new ConfigurationProviderImpl();
        this.configurationProvider.setupWithAnnaConfiguration(configuration);
        sensorManager = new CategoryOrientationAgent();
        categoryLightAgent = new CategoryLightAgent();
        CameraView cameraView = getCameraView();

        surfaceProvider = (DirectionalLayout) component.findComponentById(ResourceTable.Id_userContainer);
        cameraController = new Camera1Controller(getFractionAbility(), cameraView, configurationProvider);
        cameraController.onCreate(intent, surfaceProvider, getFractionAbility());
        currentMediaActionState = configurationProvider.getMediaAction() == Configuration.MEDIA_ACTION_VIDEO
            ? MediaAction.ACTION_VIDEO : MediaAction.ACTION_PHOTO;

        // 获取拍照和录像分辨率
        videoQualities = cameraController.getVideoQualityOptions();
        photoQualities = cameraController.getPhotoQualityOptions();

        setDeviceDefaultOrientation();

        switch (configurationProvider.getFlashMode()) {
            case Configuration.FLASH_MODE_AUTO:
                setFlashMode(Flash.FLASH_AUTO);
                break;
            case Configuration.FLASH_MODE_ON:
                setFlashMode(Flash.FLASH_ON);
                break;
            case Configuration.FLASH_MODE_OFF:
                setFlashMode(Flash.FLASH_OFF);
                break;
            default:
                break;
        }
        if (cameraFragmentControlsListener != null) {
            setMaxVideoDuration(configurationProvider.getVideoDuration());
            setMaxVideoFileSize(configurationProvider.getVideoFileSize());
        }
        notifyListeners();
        sensorManager.setSensorDataCallback(sensorEventListener,
            sensorManager.getSingleSensor(CategoryOrientation.SENSOR_TYPE_ORIENTATION), INTERVAL); // 方向传感器
        categoryLightAgent.setSensorDataCallback(lightDataCallback,
            categoryLightAgent.getSingleSensor(CategoryLight.SENSOR_TYPE_AMBIENT_LIGHT), INTERVAL); // 环境光传感器
        if (cameraFragmentControlsListener != null) {
            cameraFragmentControlsListener.lockControls();
            cameraFragmentControlsListener.allowRecord(false);
        }
    }

    private void setDeviceDefaultOrientation() {
        final int defaultOrientation = Utils.getDeviceDefaultOrientation(getFractionAbility());
        switch (defaultOrientation) {
            case Configuration.ORIENTATION_LANDSCAPE:
                configurationProvider.setDeviceDefaultOrientation(Configuration.ORIENTATION_LANDSCAPE);
                break;
            default:
                configurationProvider.setDeviceDefaultOrientation(Configuration.ORIENTATION_PORTRAIT);
                break;
        }
    }

    private CameraView getCameraView() {
        CameraView cameraView = new CameraView() {
            @Override
            public void updateCameraPreview(Size size, Component cameraPreview) {
                if (cameraFragmentControlsListener != null) {
                    cameraFragmentControlsListener.unLockControls();
                    cameraFragmentControlsListener.allowRecord(true);
                }
                setCameraPreview(cameraPreview, size);
            }

            @Override
            public void updateUiForMediaAction(int mediaAction) {
            }

            @Override
            public void updateCameraSwitcher(int numberOfCameras) {
                if (cameraFragmentControlsListener != null) {
                    cameraFragmentControlsListener.allowCameraSwitching(numberOfCameras > 1);
                }
            }

            @Override
            public void onPhotoTaken(CameraFragmentResultListener callback) {
                final String filePath = cameraController.getOutputFile().toString();
                if (cameraFragmentResultListener != null) {
                    cameraFragmentResultListener.onPhotoTaken(filePath);
                }
                if (callback != null) {
                    callback.onPhotoTaken(filePath);
                }
            }

            @Override
            public void onVideoRecordStart(int width, int height) {
                final File outputFile = cameraController.getOutputFile();
                onStartVideoRecord(outputFile);
            }

            @Override
            public void onVideoRecordStop(CameraFragmentResultListener callback) {
            }

            @Override
            public void releaseCameraPreview() {
                clearCameraPreview();
            }
        };
        return cameraView;
    }

    private void notifyListeners() {
        onFlashModeChanged();
        onActionPhotoVideoChanged();
        onCameraTypeFrontBackChanged();
    }

    @Override
    public void switchActionPhotoVideo() {
        switch (currentMediaActionState) {
            case MediaAction.ACTION_PHOTO:
                currentMediaActionState = MediaAction.ACTION_VIDEO;
                break;
            case MediaAction.ACTION_VIDEO:
                currentMediaActionState = MediaAction.ACTION_PHOTO;
                break;
            default:
                break;
        }
        onActionPhotoVideoChanged();
    }

    private void onActionPhotoVideoChanged() {
        if (cameraFragmentStateListener != null) {
            switch (currentMediaActionState) {
                case MediaAction.ACTION_VIDEO:
                    cameraController.setMediaAction(Configuration.MEDIA_ACTION_VIDEO);
                    cameraFragmentStateListener.onCameraSetupForVideo();
                    break;
                case MediaAction.ACTION_PHOTO:
                    cameraController.setMediaAction(Configuration.MEDIA_ACTION_PHOTO);
                    cameraFragmentStateListener.onCameraSetupForPhoto();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 分辨率弹窗
     */
    @Override
    public void openSettingDialog() {
        final Context context = getFractionAbility();
        CommonDialog builder = new CommonDialog(context);
        LayoutScatter instance = LayoutScatter.getInstance(context);
        Component parse = instance.parse(ResourceTable.Layout_open_setting_dialog, null, false);
        Text title = (Text) parse.findComponentById(ResourceTable.Id_title);
        Button ok = (Button) parse.findComponentById(ResourceTable.Id_ok);
        Button cancel = (Button) parse.findComponentById(ResourceTable.Id_cancel);
        ListContainer listContainer = (ListContainer) parse.findComponentById(ResourceTable.Id_listContainer);
        Component directionalLayout = parse.findComponentById(ResourceTable.Id_component); // 外部点击窗口
        directionalLayout.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component com) {
                if (builder != null && builder.isShowing()) {
                    builder.destroy();
                }
            }
        });
        try {
            // 相机和录像初始化
            photoAndVideoInit(context, title, listContainer);
            String okString = context.getResourceManager()
                .getElement(ResourceTable.String_ok_label)
                .getString(); // 设置文本字样
            ok.setText(okString);
            ok.setClickedListener(this); // 点击事件
            String cancelString = context.getResourceManager()
                .getElement(ResourceTable.String_cancel_label)
                .getString();
            cancel.setText(cancelString);
            cancel.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component com) {
                    builder.destroy();
                }
            });
        } catch (IOException e) {
            Log.error(TAG, "openSettingDialog IOException :" + e.getLocalizedMessage());
        } catch (NotExistException e) {
            Log.error(TAG, "openSettingDialog NotExistException :" + e.getLocalizedMessage());
        } catch (WrongTypeException e) {
            Log.error(TAG, "openSettingDialog WrongTypeException :" + e.getLocalizedMessage());
        }
        listContainer.setItemClickedListener(this);
        listContainer.setItemLongClickedListener(this);
        builder.setContentCustomComponent(parse);
        builder.setTransparent(true);
        builder.setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
        settingsDialog = builder;
        builder.show();
    }

    private void photoAndVideoInit(Context context, Text title, ListContainer listContainer) throws
        IOException, NotExistException, WrongTypeException {
        if (currentMediaActionState == MediaAction.ACTION_VIDEO) {
            index = getVideoOptionCheckedIndex();
            SettingItemProvider provider = new SettingItemProvider(videoQualities, context, index);
            setPhotoOrVideoItemChange(provider); // 条目选择
            listContainer.setItemProvider(provider);
            if (configurationProvider.getVideoFileSize() > 0) {
                String string = context.getResourceManager().
                    getElement(ResourceTable.String_settings_video_quality_title).getString();
                title.setText(String.format(string,
                    "(Max " + configurationProvider.getVideoFileSize() / (NUMBER_1024 * NUMBER_1024) + " MB)"));
            } else {
                String ss = context.getResourceManager().
                    getElement(ResourceTable.String_settings_video_quality_title).getString();
                title.setText(String.format(ss, ""));
            }
        } else {
            index = getPhotoOptionCheckedIndex();
            SettingItemProvider provider = new SettingItemProvider(photoQualities, context, index);
            setPhotoOrVideoItemChange(provider); // 初始化拍照条目选择
            listContainer.setItemProvider(provider);
            title.setText(context.getResourceManager().
                getElement(ResourceTable.String_settings_photo_quality_title).getString());
        }
    }

    private void setPhotoOrVideoItemChange(SettingItemProvider provider) {
        provider.setOnItemChange(new SettingItemProvider.OnItemChangeListener() {
            @Override
            public void setItemChange(Component itemChange) {
                if (itemChange != null) {
                    componentList.clear();
                    Component component1 = itemChange.findComponentById(ResourceTable.Id_component1);
                    ShapeElement element = new ShapeElement(getFractionAbility(),
                        ResourceTable.Graphic_background_component_hollow_selected);
                    component1.setBackground(element);

                    Component component2 = itemChange.findComponentById(ResourceTable.Id_component2);
                    ShapeElement element1 = new ShapeElement(getFractionAbility(),
                        ResourceTable.Graphic_background_component_solid_selected);
                    component2.setBackground(element1);
                    component2.setScale(SCALE_0_5, SCALE_0_5);
                    component2.setVisibility(Component.VISIBLE);
                    componentList.add(component1);
                    componentList.add(component2);
                }
            }
        });
    }

    @Override
    public PhotoQualityOption[] getPhotoQualities() {
        List<PhotoQualityOption> photoQualityOptions = new ArrayList<>();

        for (CharSequence photoQuality : photoQualities) {
            photoQualityOptions.add((PhotoQualityOption) photoQuality);
        }
        return photoQualityOptions.toArray(new PhotoQualityOption[photoQualityOptions.size()]);
    }

    @Override
    public void switchCameraTypeFrontBack() {
        if (cameraFragmentControlsListener != null) {
            cameraFragmentControlsListener.lockControls();
            cameraFragmentControlsListener.allowRecord(false);
        }
        int cameraFace = Configuration.CAMERA_FACE_REAR; // 默认为后置摄像头
        switch (currentCameraType) {
            case CameraInfo.FacingType.CAMERA_FACING_FRONT:
                currentCameraType = CameraInfo.FacingType.CAMERA_FACING_BACK;
                cameraFace = Configuration.CAMERA_FACE_REAR;
                break;
            case CameraInfo.FacingType.CAMERA_FACING_BACK:
                currentCameraType = CameraInfo.FacingType.CAMERA_FACING_FRONT;
                cameraFace = Configuration.CAMERA_FACE_FRONT;
                break;
            default:
                break;
        }

        cameraController.switchCamera(cameraFace);

        if (cameraFragmentControlsListener != null) {
            cameraFragmentControlsListener.unLockControls();
        }
    }

    @Override
    public void toggleFlashMode() {
        switch (currentFlashMode) {
            case Flash.FLASH_AUTO:
                currentFlashMode = Flash.FLASH_OFF;
                break;
            case Flash.FLASH_OFF:
                currentFlashMode = Flash.FLASH_ON;
                break;
            case Flash.FLASH_ON:
                currentFlashMode = Flash.FLASH_AUTO;
                break;
            default:
                break;
        }
        onFlashModeChanged();
    }

    @Override
    public void setStateListener(CameraFragmentStateListener stateListener) {
        this.cameraFragmentStateListener = stateListener;
    }

    @Override
    public void setTextListener(CameraFragmentVideoRecordTextListener textListener) {
        this.cameraFragmentVideoRecordTextListener = textListener;
    }

    @Override
    public void setControlsListener(CameraFragmentControlsListener controlsListener) {
        this.cameraFragmentControlsListener = controlsListener;
    }

    @Override
    public void setResultListener(CameraFragmentResultListener resultListener) {
        this.cameraFragmentResultListener = resultListener;
    }

    private void onScreenRotation(int degrees) {
        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.shouldRotateControls(degrees);
        }
        rotateSettingsDialog(degrees);
    }

    private void setRecordState(@Record.RecordState int recordState) {
        this.currentRecordState = recordState;
    }

    private void rotateSettingsDialog(int degrees) {
        if (settingsDialog != null && settingsDialog.isShowing()) {
            DirectionalLayout layout = (DirectionalLayout) settingsDialog.getContentCustomComponent()
                .findComponentById(ResourceTable.Id_setting_content_layout);
            if (degrees != DEFAULT) {
                layout.setRotation(degrees);
            }
        }
    }

    private int getVideoOptionCheckedIndex() {
        int checkedIndex = DEFAULT;

        final int mediaQuality = configurationProvider.getMediaVideoQuality();

        if (mediaQuality == Configuration.MEDIA_QUALITY_HIGH) {
            checkedIndex = 0;
        } else if (mediaQuality == Configuration.MEDIA_QUALITY_MEDIUM) {
            checkedIndex = DEFAULT_1;
        } else if (mediaQuality == Configuration.MEDIA_QUALITY_LOW) {
            checkedIndex = DEFAULT_2;
        }

        return checkedIndex;
    }

    private int getPhotoOptionCheckedIndex() {
        int checkedIndex = DEFAULT;

        final int mediaQuality = configurationProvider.getMediaPhotoQuality();

        if (mediaQuality == Configuration.MEDIA_QUALITY_HIGHEST) {
            checkedIndex = 0;
        } else if (mediaQuality == Configuration.MEDIA_QUALITY_HIGH) {
            checkedIndex = DEFAULT_1;
        } else if (mediaQuality == Configuration.MEDIA_QUALITY_MEDIUM) {
            checkedIndex = DEFAULT_2;
        } else if (mediaQuality == Configuration.MEDIA_QUALITY_LOWEST) {
            checkedIndex = DEFAULT_3;
        }
        return checkedIndex;
    }

    @Override
    public void takePhotoOrCaptureVideo(CameraFragmentResultListener resultListener, String directoryPath,
                                        String fileName) {
        switch (currentMediaActionState) {
            case MediaAction.ACTION_PHOTO:
                takePhoto(resultListener, directoryPath, fileName);
                break;
            case MediaAction.ACTION_VIDEO:
                switch (currentRecordState) {
                    case Record.RECORD_IN_PROGRESS_STATE:
                        stopRecording(resultListener);
                        break;
                    default:
                        startRecording(directoryPath, fileName);
                        break;
                }
                break;
            default:
                break;
        }
    }

    private void takePhoto(CameraFragmentResultListener callback, String directoryPath, String fileName) {
        setRecordState(Record.TAKE_PHOTO_STATE);
        this.cameraController.takePhoto(callback, directoryPath, fileName);
        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.onRecordStatePhoto();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        cameraController.releaseCamera();
        sensorManager.releaseSensorDataCallback(sensorEventListener,
            sensorManager.getSingleSensor(CategoryOrientation.SENSOR_TYPE_ORIENTATION)); // 释放所有传感器
        categoryLightAgent.releaseSensorDataCallback(lightDataCallback,
            categoryLightAgent.getSingleSensor(CategoryLight.SENSOR_TYPE_AMBIENT_LIGHT));
        if (cameraFragmentControlsListener != null) {
            cameraFragmentControlsListener.lockControls();
            cameraFragmentControlsListener.allowRecord(false);
        }
        cameraController.onDestroy();
    }

    // 开始录制
    private void startRecording(String directoryPath, String fileName) {
        setRecordState(Record.RECORD_IN_PROGRESS_STATE);
        this.cameraController.startVideoRecord(directoryPath, fileName);
        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.onRecordStateVideoInProgress();
        }
    }

    private void stopRecording(CameraFragmentResultListener callback) {
        setRecordState(Record.READY_FOR_RECORD_STATE);
        this.cameraController.stopVideoRecord(callback);

        this.onStopVideoRecord(callback);

        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.onRecordStateVideoReadyForRecord();
        }
    }

    private void onStopVideoRecord(CameraFragmentResultListener callback) {
        if (cameraFragmentControlsListener != null) {
            cameraFragmentControlsListener.allowRecord(false);
        }
        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.onStopVideoRecord();
        }
        setRecordState(Record.READY_FOR_RECORD_STATE);

        if (countDownTimer != null) {
            countDownTimer.stop();
        }

        final int mediaAction = configurationProvider.getMediaAction();
        if (cameraFragmentControlsListener != null) {
            if (mediaAction != Configuration.MEDIA_ACTION_UNSPECIFIED) {
                cameraFragmentControlsListener.setMediaActionSwitchVisible(true);
            } else {
                cameraFragmentControlsListener.setMediaActionSwitchVisible(false);
            }
        }

        final String filePath = this.cameraController.getOutputFile().toString();
        if (cameraFragmentResultListener != null) {
            cameraFragmentResultListener.onVideoRecorded(filePath);
        }

        if (callback != null) {
            callback.onVideoRecorded(filePath);
        }
    }

    private void setCameraPreview(Component preview, Size previewSize) {
        videoQualities = cameraController.getVideoQualityOptions();
        photoQualities = cameraController.getPhotoQualityOptions();
    }

    private void onStartVideoRecord(File mediaFile) {
        setMediaFilePath(mediaFile);
        if (maxVideoFileSize > 0) {
            if (cameraFragmentVideoRecordTextListener != null) {
                cameraFragmentVideoRecordTextListener.setRecordSizeText(maxVideoFileSize,
                    "1Mb" + " / " + maxVideoFileSize / (NUMBER_1024 * NUMBER_1024) + MB);
                cameraFragmentVideoRecordTextListener.setRecordSizeTextVisible(true);
            }
            final long fileSize = mediaFile.length() / (NUMBER_1024 * NUMBER_1024);
            if (cameraFragmentVideoRecordTextListener != null) {
                cameraFragmentVideoRecordTextListener.setRecordSizeText(maxVideoFileSize,
                    fileSize + MB + " / " + maxVideoFileSize / (NUMBER_1024 * NUMBER_1024) + MB);
            }
        }
        if (countDownTimer == null) {
            this.countDownTimer = new TimerTask(timerCallBack);
        }
        countDownTimer.start();

        if (cameraFragmentStateListener != null) {
            cameraFragmentStateListener.onStartVideoRecord(mediaFile);
        }
    }

    private void setMediaFilePath(File mediaFile) {
    }

    private void clearCameraPreview() {
    }

    private void setFlashMode(@Flash.FlashMode int mode) {
        this.currentFlashMode = mode;
        onFlashModeChanged();
    }

    private void onFlashModeChanged() {
        switch (currentFlashMode) {
            case Flash.FLASH_AUTO:
                if (cameraFragmentStateListener != null) {
                    cameraFragmentStateListener.onFlashAuto();
                }
                configurationProvider.setFlashMode(Configuration.FLASH_MODE_AUTO);
                this.cameraController.setFlashMode(Configuration.FLASH_MODE_AUTO);
                break;
            case Flash.FLASH_ON:
                if (cameraFragmentStateListener != null) {
                    cameraFragmentStateListener.onFlashOn();
                }
                configurationProvider.setFlashMode(Configuration.FLASH_MODE_ON);
                this.cameraController.setFlashMode(Configuration.FLASH_MODE_ON);
                break;
            case Flash.FLASH_OFF:
                if (cameraFragmentStateListener != null) {
                    cameraFragmentStateListener.onFlashOff();
                }
                configurationProvider.setFlashMode(Configuration.FLASH_MODE_OFF);
                this.cameraController.setFlashMode(Configuration.FLASH_MODE_OFF);
                break;
            default:
                break;
        }
    }

    private void setMaxVideoDuration(int maxVideoDurationInMillis) {
        if (maxVideoDurationInMillis > 0) {
            this.countDownTimer = new CountdownTask(timerCallBack, maxVideoDurationInMillis);
        } else {
            this.countDownTimer = new TimerTask(timerCallBack);
        }
    }

    private void setMaxVideoFileSize(long maxVideoFileSize) {
        this.maxVideoFileSize = maxVideoFileSize;
    }

    private void setCameraTypeFrontBack(int cameraFace) {
        int tempCameraFace = cameraFace;
        switch (tempCameraFace) {
            case Configuration.CAMERA_FACE_FRONT: // 前置
                currentCameraType = CameraInfo.FacingType.CAMERA_FACING_FRONT;
                tempCameraFace = Configuration.CAMERA_FACE_FRONT;
                break;
            case Configuration.CAMERA_FACE_REAR: // 后置
                currentCameraType = CameraInfo.FacingType.CAMERA_FACING_BACK;
                tempCameraFace = Configuration.CAMERA_FACE_REAR;
                break;
            default:
                break;
        }
        onCameraTypeFrontBackChanged();
        this.cameraController.switchCamera(cameraFace);
    }

    private void onCameraTypeFrontBackChanged() {
        if (cameraFragmentStateListener != null) {
            switch (currentCameraType) {
                case CameraInfo.FacingType.CAMERA_FACING_BACK:
                    cameraFragmentStateListener.onCurrentCameraBack();
                    break;
                case CameraInfo.FacingType.CAMERA_FACING_FRONT:
                    cameraFragmentStateListener.onCurrentCameraFront();
                    break;
                default:
                    break;
            }
        }
    }

    private void showItemAnimator(Component com) {
        cancelComponentAnimator();
        Component component1 = com.findComponentById(ResourceTable.Id_component1);
        ShapeElement element = new ShapeElement(getFractionAbility(),
            ResourceTable.Graphic_background_component_hollow_selected);
        component1.setBackground(element);

        Component component2 = com.findComponentById(ResourceTable.Id_component2);
        ShapeElement element1 = new ShapeElement(getFractionAbility(),
            ResourceTable.Graphic_background_component_solid_selected);
        component2.setBackground(element1);
        component2.setVisibility(Component.VISIBLE);
        componentList.add(component1);
        componentList.add(component2);
        animatorProperty1 = component2.createAnimatorProperty(); // 开始动画
        animatorProperty1
            .scaleXBy(1) // 从哪里开始
            .scaleYBy(1)
            .scaleX(SCALE_0_5) // 到哪里结束
            .scaleY(SCALE_0_5)
            .setDuration(SCALE_TIME_60);
        animatorProperty1.start();
    }

    private void cancelComponentAnimator() {
        if (componentList.size() > 0) {
            Component component1 = componentList.get(0);
            ShapeElement element1 = new ShapeElement(getFractionAbility(),
                ResourceTable.Graphic_background_component_hollow_normal);
            component1.setBackground(element1);
            Component component2 = componentList.get(1);
            ShapeElement element2 = new ShapeElement(getFractionAbility(),
                ResourceTable.Graphic_background_component_solid_normal);
            component2.setBackground(element2);
            animatorProperty = component2.createAnimatorProperty();
            animatorProperty
                .scaleXBy(SCALE_0_5) // 从哪里开始
                .scaleYBy(SCALE_0_5)
                .scaleX(1) // 到哪里结束
                .scaleY(1);
            animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    component2.setVisibility(Component.HIDE);
                }
            });
            animatorProperty.setDuration(SCALE_TIME_80);
            animatorProperty.start();
            componentList.clear();
        }
    }

    @Override
    public void onItemClicked(ListContainer listContainer, Component com, int position, long ll) {
        if (currentMediaActionState == MediaAction.ACTION_PHOTO) { // 拍照
            newPhotoQuality = ((PhotoQualityOption) photoQualities[position]).getMediaQuality();
        } else { // 视频
            newVideoQuality = ((VideoQualityOption) videoQualities[position]).getMediaQuality();
        }
        if (index != position) {
            index = position;
            showItemAnimator(com);
        }
    }

    @Override
    public boolean onItemLongClicked(ListContainer listContainer, Component com, int position, long ll) {
        if (currentMediaActionState == MediaAction.ACTION_PHOTO) { // 拍照
            newPhotoQuality = ((PhotoQualityOption) photoQualities[position]).getMediaQuality();
        } else { // 视频
            newVideoQuality = ((VideoQualityOption) videoQualities[position]).getMediaQuality();
        }
        if (index != position) {
            index = position;
            showItemAnimator(com);
        }
        return false;
    }

    @Override
    protected void onBackground() {
        super.onBackground();
        isBackground = true;
        if (cameraController != null) {
            cameraController.releaseCamera();
        }
    }

    /**
     * 进入前台
     */
    @Override
    protected void onActive() { // 在这里判断当前文件夹是否被删除,如果是就重新创建
        super.onActive();
        if (isBackground) {
            isBackground = false;
            if (cameraController != null) {
                cameraController.openCamera(); // 重新打开相机
            }
        }
    }

    @Override
    public void onClick(Component comp) {
        if (currentMediaActionState == MediaAction.ACTION_VIDEO) { // 设置视频图片质量
            if (newVideoQuality > 0 && newVideoQuality != configurationProvider.getMediaVideoQuality()) {
                configurationProvider.setMediaVideoQuality(newVideoQuality);
                if (cameraFragmentControlsListener != null) {
                    cameraFragmentControlsListener.lockControls();
                }
                cameraController.switchQuality();
            }
        } else { // 设置图片质量
            if (newPhotoQuality > 0 && newPhotoQuality != configurationProvider.getMediaPhotoQuality()) {
                configurationProvider.setMediaPhotoQuality(newPhotoQuality);
                if (cameraFragmentControlsListener != null) {
                    cameraFragmentControlsListener.lockControls();
                }
                cameraController.switchQuality();
            }
        }
        settingsDialog.destroy();
    }
}
